package com.platform.qujia.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.platform.qujia.constantEnum.BatchTaskCons;
import com.platform.qujia.dao.WxMessageTemplateMapper;
import com.platform.qujia.enums.BatchTaskStatus;
import com.platform.qujia.enums.WxTemplateEnum;
import com.platform.qujia.pojo.*;
import com.platform.qujia.pojo.dto.SendWxTemplateMessageRunnableParam;
import com.platform.qujia.pojo.wx.WxTemplateMessageSendRequest;
import com.platform.qujia.service.*;
import com.platform.qujia.utils.JsonUtils;
import com.platform.qujia.utils.LocalDateTimeUtil;
import com.platform.qujia.utils.exception.CustomException;
import com.platform.qujia.utils.weixinapp.WxPushUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
@Slf4j
public class WxMessageTemplateServiceImpl implements WxMessageTemplateService {

    private static final int SEND_WX_TEMPLATE_MESSAGE_BATCH_SIZE = 300;

    @Autowired
    private WxMessageTemplateMapper wxMessageTemplateMapper;

    @Autowired
    private AppUserInfoService appUserInfoService;

    @Autowired
    private WxPushUtil wxPushUtil;
    @Autowired
    private EnterpriseService enterpriseService;
    @Resource
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private BatchTaskService batchTaskService;
    @Autowired
    private BatchSubtaskService batchSubtaskService;
    @Autowired
    private Map<String, WxTemplateParamsGeneral> wxTemplateParamsGeneralMap;

    @Override
    public WxMessageTemplate getByEnterpriseIdAndType(Long enterpriseId, Integer type) {
        return wxMessageTemplateMapper.getByEnterpriseIdAndType(enterpriseId, type);
    }

    @Override
    public void WxMessageTemplatePushForRedis() {
        List<JSONObject> redisList = new ArrayList<>();
        String redisParams = (String) redisTemplate.opsForList().rightPop(WxMessageTemplate.WX_MESSAGE_TEMPLATE_REDIS_KEY);
        while (redisParams != null) {
            JSONObject jsonObjectParams = JSONUtil.parseObj(redisParams);
            redisList.add(jsonObjectParams);
            redisParams = (String) redisTemplate.opsForList().rightPop(WxMessageTemplate.WX_MESSAGE_TEMPLATE_REDIS_KEY);
        }
        if (ObjectUtils.isEmpty(redisList)) return;

        log.info("油站油品调价-redis中参数：{}", redisList);
        redisList.forEach(params -> {
            try {
                Date now = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date pushDate = sdf.parse(String.valueOf(params.get("pushDate")));
                if (pushDate.before(now)) {
                    List<AppUserInfo> appUserInfoList = appUserInfoService.selectAppUserInfoByStationId(Long.valueOf(params.get("enterpriseId").toString()));
                    if (ObjectUtils.isEmpty(appUserInfoList)) return;
                    for (AppUserInfo appUserInfo : appUserInfoList) {
                        if (StringUtils.isEmpty(appUserInfo.getBlogOpenid())) continue;

                        Map<String, String> templateParams = new HashMap<>();
                        templateParams.put("openid", appUserInfo.getBlogOpenid());
                        templateParams.put("detail", params.get("stationName") + "，" + params.get("oilName")+"最新价格");
                        templateParams.put("priceChange",  params.get("price").toString());
                        templateParams.put("effectdate", String.valueOf(params.get("date")));
                        log.info("油站油品调价-微信模板参数：{}", templateParams);
                        wxPushUtil.sendTemplateMsg(Integer.valueOf(String.valueOf(params.get("enterpriseId"))), templateParams, WxTemplateEnum.OIL_PRICE_CHANGE);
                    }
                } else {
                    redisTemplate.opsForList().leftPush(WxMessageTemplate.WX_MESSAGE_TEMPLATE_REDIS_KEY, JSONUtil.toJsonStr(params));
                }
            } catch (ParseException e) {
                log.error("油站油品调价-微信模板推送失败，e:{ }", e);
            }
        });
    }

    @Override
    public void batchSendOilPriceAdjustWxTemplateMessageFromRedis() {
        List<String> redisList = new ArrayList<>();
        String redisParams = redisTemplate.opsForList().rightPop(WxMessageTemplate.WX_MESSAGE_TEMPLATE_REDIS_KEY);
        while (redisParams != null) {
            redisList.add(redisParams);
            redisParams = redisTemplate.opsForList().rightPop(WxMessageTemplate.WX_MESSAGE_TEMPLATE_REDIS_KEY);
        }
        if (ObjectUtils.isEmpty(redisList)) return;
//        redisList.add("{\"pushDate\":\"2023-11-22 15:10:00\",\"stationName\":\"批量推送测试\",\"oilName\":\"95#\",\"price\":\"8.90\",\"date\":\"2023-11-22 15:00:00\",\"enterpriseId\":\"246\"}");

        log.info("油站油品调价-redis中参数：{}", redisList);
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(LocalDateTimeUtil.YYYY_MM_DD_HH_MM_SS);
        for (String templateValue : redisList) {
            com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(templateValue);
            LocalDateTime pushDate = LocalDateTime.parse(jsonObject.getString("pushDate"), formatter);
            if (pushDate.isBefore(now)) {
                String stationName = jsonObject.getString("stationName");
                String oilName = jsonObject.getString("oilName");
                String price = jsonObject.getString("price");
                String date = jsonObject.getString("date");
                Integer enterpriseId = jsonObject.getInteger("enterpriseId");
                Enterprise enterprise = enterpriseService.selectEnterpriseInfo(enterpriseId);
                if (enterprise == null || StringUtils.isBlank(enterprise.getGzhAppId())) {
                    log.info("油企未找到或公众号未设置appId,enterpriseId:{}",enterpriseId);
                    continue;
                }
                Map<String, String> templateParams = new HashMap<>();
                templateParams.put("detail", stationName + "，" + oilName+"最新价格");
                templateParams.put("priceChange", price);
                templateParams.put("effectdate",date);
                createSendWxTemplateMessageBatchTask(enterprise,WxTemplateEnum.OIL_PRICE_CHANGE,templateParams,enterpriseId+"-油价推送");
            }else{
                redisTemplate.opsForList().leftPush(WxMessageTemplate.WX_MESSAGE_TEMPLATE_REDIS_KEY,templateValue);
            }
        }
    }

    @Override
    public void batchSendActivityNotifyWxTemplateMessage(ActivityMessagePushRecord record) {
        Enterprise enterprise = enterpriseService.selectEnterpriseInfo(Math.toIntExact(record.getEnterpriseId()));
        if (enterprise == null || StringUtils.isBlank(enterprise.getGzhAppId())) {
            log.info("油企未找到或公众号未设置appId,enterpriseId:{}",record.getEnterpriseId());
            return;
        }
        Map<String, String> templateParams = new HashMap<>();
        templateParams.put("content", record.getContent());
        templateParams.put("stationName",record.getStationName());
        createSendWxTemplateMessageBatchTask(enterprise,WxTemplateEnum.CREATE_ACTIVITY,templateParams,record.getEnterpriseId()+"-活动通知");
    }

    private void createSendWxTemplateMessageBatchTask(Enterprise enterprise, WxTemplateEnum templateEnum, Map<String, String> templateParams,String taskName){
        Integer enterpriseId = enterprise.getEnterpriseId();
        WxMessageTemplate wxMessageTemplate = wxMessageTemplateMapper.getByEnterpriseIdAndType(Long.valueOf(enterpriseId), templateEnum.getCode());
        if (wxMessageTemplate == null) {
            log.info("油企未配置对应模板,enterpriseId:[{}],template:[{}]", enterpriseId,templateEnum);
            return;
        }
        AppUserInfo example = new AppUserInfo();
        example.setStationId(enterpriseId);
        int total = appUserInfoService.countByExample(example);
        if (total>0) {
            WxTemplateMessageSendRequest templateSendRequest = buildWxTemplateSendRequest(templateParams, wxMessageTemplate);
            if (templateSendRequest == null) {
                log.info("模板消息构建参数错误");
                return;
            }
            SendWxTemplateMessageRunnableParam runnableParam = new SendWxTemplateMessageRunnableParam();
            runnableParam.setSendRequest(templateSendRequest);
            runnableParam.setEnterpriseId(enterpriseId);
            runnableParam.setGzhAppId(enterprise.getGzhAppId());
            runnableParam.setGzhAppSecret(enterprise.getGzhAppSecret());
            String context = null;
            try {
                context = JsonUtils.objectToJson(runnableParam);
            } catch (JsonProcessingException e) {
                log.error(e.getMessage(), e);
                return;
            }
            int chunk = total/ SEND_WX_TEMPLATE_MESSAGE_BATCH_SIZE;
            if(total % SEND_WX_TEMPLATE_MESSAGE_BATCH_SIZE > 0){
                chunk++;
            }
            LocalDateTime now = LocalDateTime.now();
            BatchTask task = new BatchTask();
            task.setTaskType(BatchTaskCons.TASK_TYPE_SEND_WX_TEMPLATE_MESSAGE);
            task.setTaskName(taskName);
            task.setTaskContext(context);
            task.setSubtaskNum(chunk);
            task.setTotalItemNum(total);
            task.setCreateTime(now);
            batchTaskService.save(task);

            ArrayList<BatchSubtask> subtasks = new ArrayList<>(chunk);
            for (int i = 0; i < chunk; i++) {
                BatchSubtask subtask = new BatchSubtask();
                subtask.setBatchId(task.getId());
                subtask.setTaskType(BatchTaskCons.TASK_TYPE_SEND_WX_TEMPLATE_MESSAGE);
                subtask.setSubtaskName(taskName+"-"+i);
                subtask.setSubtaskParam(String.format("{\"offset\":\"%d\",\"limit\":\"%d\"}",i * SEND_WX_TEMPLATE_MESSAGE_BATCH_SIZE, SEND_WX_TEMPLATE_MESSAGE_BATCH_SIZE));
                subtask.setCreateTime(now);
                if (i==chunk-1) {
                    subtask.setItemNum(total- SEND_WX_TEMPLATE_MESSAGE_BATCH_SIZE *i);
                }else{
                    subtask.setItemNum(SEND_WX_TEMPLATE_MESSAGE_BATCH_SIZE);
                }
                subtask.setSubtaskStatus(BatchTaskStatus.NOT_STARTED);
                subtasks.add(subtask);
            }
            if (!subtasks.isEmpty()) {
                batchSubtaskService.saveBatch(subtasks);
            }
        }
    }

    private WxTemplateMessageSendRequest buildWxTemplateSendRequest(Map<String,String> templateParams, WxMessageTemplate wxMessageTemplate) {
        WxTemplateEnum templateEnum = WxTemplateEnum.getByCode(wxMessageTemplate.getTemplateType());
        if (templateEnum == null) {
            return null;
        }

        if (ObjectUtils.isEmpty(wxMessageTemplate.getTemplateId())) return null;

        WxTemplateMessageSendRequest templateSendRequest = new WxTemplateMessageSendRequest();
        templateSendRequest.setTemplateId(wxMessageTemplate.getTemplateId());
        templateSendRequest.setTouser(templateParams.get("openid"));
        // 跳转链接
        if (StringUtils.isNotBlank(wxMessageTemplate.getTemplateUrl())) {
            templateSendRequest.setUrl(wxMessageTemplate.getTemplateUrl());
        }
        // 标题
        HashMap<String, Map<String, String>> data = new HashMap<>();
        if (StringUtils.isNotBlank(wxMessageTemplate.getTemplateName())) {
            data.put("first", Collections.singletonMap("value",wxMessageTemplate.getTemplateName()));
        }
        // 备注
        if (StringUtils.isNotBlank(wxMessageTemplate.getTemplateRemark())) {
            HashMap<String, String> remark = new HashMap<>();
            remark.put("value", wxMessageTemplate.getTemplateRemark());
            remark.put("color", "#000000");
            data.put("remark", remark);
        }

        // 设置其他模板内容
        if (StringUtils.isNotBlank(wxMessageTemplate.getTemplateContent())) {
            List<String> contents = Arrays.asList(wxMessageTemplate.getTemplateContent().split(","));
            wxTemplateParamsGeneralMap.get(templateEnum.getType()).setWxTemplateContent(contents, templateParams, data);
        }
        templateSendRequest.setData(data);
        return templateSendRequest;
    }

}
